package com.yingxin.yx.framework.commons.utlis;

import cn.hutool.core.util.ObjectUtil;
import com.yingxin.yx.framework.commons.vo.update.BeanUpdateRespVo;
import com.yingxin.yx.framework.render.core.ForUpdate;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BeanUpdateUtils {

    private static String checkString(String checkStr){
        if( StringUtils.isEmpty( checkStr ) ){
            return "";
        }
        return checkStr;
    }

    /**
     * 移除字符串的最后一个指定字符
     * @param str
     * @return
     */
    private static String removeLastNotation(String str, String notation){
        str = str.replaceAll("null", "");
        if( ! str.isEmpty() ){
            if( ! notation.isEmpty() ){
                return Stream.of( str.split( notation ) ).collect( Collectors.joining( notation ) );
            }
        }
        return str;
    }

    /**
     * 替换值
     * @param replace {"是_1"，"否_0"}
     * @param value
     * @return
     */
    private static Object replaceValue(String[] replace, Object value){
        for (String s : replace) {
            String[] str = s.split("_");
            if (str[1].equals(value)){
                value = str[0];
                break;
            }
        }
        return value;
    }


    /**
     * 新增bean时返回bean的所有列
     */
    public static <T> String getObjectFields( T bean ) throws IllegalAccessException {
        Field[] fields = bean.getClass().getDeclaredFields();
        if( ObjectUtil.isEmpty( fields ) ) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        for(Field field : fields) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(ForUpdate.class)) {
                if( !field.getAnnotation( ForUpdate.class ).primaryKey() ){
                   if (field.getAnnotation(ForUpdate.class).isShow() || !Objects.isNull(field.get( bean ))){
                       builder.append( field.getAnnotation(ForUpdate.class).fieldName() );
                       builder.append("：");
                       builder.append( field.get( bean ) );
                       builder.append("，");
                   }
                }
            }
        }
        return removeLastNotation( builder.toString(), "，" );
    }

    /**
     * 获取bean的变更内容 返回object
     * @param newBean 改前的bean
     * @param oldBean 改后的bean
     * @return <T>
     * @param <T>
     */
    public static <T> BeanUpdateRespVo getChangedObjectFields(T newBean, T oldBean){
        Field[] fields = newBean.getClass().getDeclaredFields();
        if( ObjectUtil.isEmpty( fields ) ) {
            return null;
        }
        BeanUpdateRespVo respVo = new BeanUpdateRespVo();
        StringBuilder newBuilder = new StringBuilder();
        StringBuilder oldBuilder = new StringBuilder();

        for(Field field : fields) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(ForUpdate.class)) {
                try {
                    Object newValue = field.get(newBean);
                    Object oldValue = field.get(oldBean);
                    // 是否有值
                    if (!Objects.isNull(newValue) || !Objects.isNull(oldValue)){
                        // 是否强制显示
                        if( field.getAnnotation(ForUpdate.class).isShow() ){
                            // 改前描述
                            newBuilder.append( field.getAnnotation(ForUpdate.class).fieldName() );
                            newBuilder.append("：");
                            // 替换值 replaceValue（）
                            newBuilder.append( replaceValue(field.getAnnotation(ForUpdate.class).replace(),newValue) );
                            newBuilder.append("，");
                            // 改后描述
                            oldBuilder.append( field.getAnnotation(ForUpdate.class).fieldName() );
                            oldBuilder.append("：");
                            // 替换值
                            oldBuilder.append( replaceValue(field.getAnnotation(ForUpdate.class).replace(),oldValue) );
                            oldBuilder.append("，");
                        } else if(!Objects.equals(newValue, oldValue)) {
                            // 改前描述
                            newBuilder.append( field.getAnnotation(ForUpdate.class).fieldName() );
                            newBuilder.append("：");
                            // 替换值
                            newBuilder.append( replaceValue(field.getAnnotation(ForUpdate.class).replace(),newValue) );
                            newBuilder.append("，");

                            // 改后描述
                            oldBuilder.append( field.getAnnotation(ForUpdate.class).fieldName() );
                            oldBuilder.append("：");
                            // 替换值
                            oldBuilder.append( replaceValue(field.getAnnotation(ForUpdate.class).replace(),oldValue) );
                            oldBuilder.append("，");
                        }
                    }
                } catch (Exception e) {
                }
            }
        }

        respVo.setNewString( removeLastNotation( newBuilder.toString(), "，" ) );
        respVo.setOldString( removeLastNotation( oldBuilder.toString(), "，" ) );

        return respVo;
    }

    /**
     * 获取单据和明细的变更内容 返回object
     * @param newBean 改前的bean bill
     * @param oldBean 改后的bean bill
     * @return <T>
     * @param <T>
     */
    public static <T,I> BeanUpdateRespVo getChangedBillAndItemsField(
            T newBean, T oldBean, List<I> newItems, List<I> oldItems) throws IllegalAccessException {
        BeanUpdateRespVo respVo = new BeanUpdateRespVo();
        StringBuilder newBuilder = new StringBuilder();
        StringBuilder oldBuilder = new StringBuilder();
        StringBuilder newItemBuilder = new StringBuilder();
        StringBuilder oldItemBuilder = new StringBuilder();

        if( ObjectUtil.isNotEmpty( newBean ) && ObjectUtil.isNotEmpty( oldBean ) ) {
            BeanUpdateRespVo bill = getChangedObjectFields(newBean, oldBean);
            if (StringUtils.isNotEmpty(bill.getNewString())) {
                newBuilder.append("单据改前信息：");
                newBuilder.append("\n");
                newBuilder.append(bill.getNewString());
                newBuilder.append("\n");
            }
            if (StringUtils.isNotEmpty(bill.getOldString())) {
                oldBuilder.append("单据改后信息：");
                oldBuilder.append("\n");
                oldBuilder.append(bill.getOldString());
                oldBuilder.append("\n");
            }
        }

        int rownum = 1;

        // 改后列表
        for( I o : oldItems ){

            // 是否找到
            boolean ischeck = false;

            // 改前列表
            for( I n : newItems ){
                // 获取Obj的所有属性
                Field[] ofields = o.getClass().getDeclaredFields();

                for (Field ofield : ofields) {
                    ofield.setAccessible(true);
                    if (ofield.isAnnotationPresent(ForUpdate.class)) {
                        ForUpdate forUpdate = ofield.getAnnotation(ForUpdate.class);
                        if ( forUpdate.primaryKey() ) {
                            try {
                                Object okey = ofield.get( o );
                                Object nkey = ofield.get( n );
                                if( Objects.equals( okey, nkey ) ){
                                    // 已经找到
                                    ischeck = true;

                                    BeanUpdateRespVo item = getChangedObjectFields( n, o );
                                    if(StringUtils.isNotEmpty( item.getOldString() ) ) {

                                        newItemBuilder.append("第" + rownum + "条：");
                                        newItemBuilder.append(item.getNewString());
                                        newItemBuilder.append("\n");

                                        oldItemBuilder.append("第" + rownum + "条：");
                                        oldItemBuilder.append(item.getOldString());
                                        oldItemBuilder.append("\n");

                                        rownum++;

                                        break;
                                    }
                                }
                            }catch (Exception e){ }
                        }
                    }
                }
            }

            // 未找到，视为新增
            if( !ischeck ){
                oldItemBuilder.append("新增-第" + rownum + "条：");
                oldItemBuilder.append( getObjectFields( o ) );
                oldItemBuilder.append("\n");

                rownum++;
            }
        }

        // 排查出改后已经删除的
        // 改前列表
        for( I n : newItems ){

            // 是否找到
            boolean ischeck = false;

            // 改后列表
            for( I o : oldItems ){
                // 获取Obj的所有属性
                Field[] nfields = n.getClass().getDeclaredFields();
                for (Field nfield : nfields) {
                    nfield.setAccessible(true);
                    if ( nfield.isAnnotationPresent( ForUpdate.class ) ) {
                        ForUpdate forUpdate = nfield.getAnnotation(ForUpdate.class);
                        if (forUpdate.primaryKey()) {
                            try {
                                Object okey = nfield.get( o );
                                Object nkey = nfield.get( n );
                                if (Objects.equals(okey, nkey)) {
                                    ischeck = true;
                                    break;
                                }
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }

            // 未找到，视为删除
            if( !ischeck ){
                oldItemBuilder.append("删除-第" + rownum + "条：");
                oldItemBuilder.append( getObjectFields( n ) );
                oldItemBuilder.append("\n");
                rownum++;
            }
        }
        if( StringUtils.isNotEmpty( newItemBuilder.toString() ) ){
            newBuilder.append("明细改前信息：");
            newBuilder.append("\n");
            newBuilder.append( newItemBuilder.toString() );
        }
        if( StringUtils.isNotEmpty( oldItemBuilder.toString() ) ){
            oldBuilder.append("明细改后信息：");
            oldBuilder.append("\n");
            oldBuilder.append( oldItemBuilder.toString() );
        }
        respVo.setOldString( oldBuilder.toString() );
        respVo.setNewString( newBuilder.toString() );
        return respVo;
    }

}
